/*---------------------------------------------------------------------------
 *
 * Ryu 浮点输出用于单精度。
 *
 * Portions Copyright (c) 2018-2022, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *	  src/common/f2s.c
 *
 * This is a modification of code taken from github.com/ulfjack/ryu under the
 * terms of the Boost license (not the Apache license). The original copyright
 * notice follows:
 *
 * Copyright 2018 Ulf Adams
 *
 * The contents of this file may be used under the terms of the Apache
 * License, Version 2.0.
 *
 *     (See accompanying file LICENSE-Apache or copy at
 *      http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Alternatively, the contents of this file may be used under the terms of the
 * Boost Software License, Version 1.0.
 *
 *     (See accompanying file LICENSE-Boost or copy at
 *      http://www.boost.org/LICENSE_1_0.txt)
 *
 * Unless required by applicable law or agreed to in writing, this software is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.
 *
 *---------------------------------------------------------------------------
 */

#ifndef FRONTEND
#include "postgres.h"
#else
#include "postgres_fe.h"
#endif

#include "common/shortest_dec.h"
#include "digit_table.h"
#include "ryu_common.h"

#define FLOAT_MANTISSA_BITS 23
#define FLOAT_EXPONENT_BITS 8
#define FLOAT_BIAS 127

/*
 * 此表由上游通过 PrintFloatLookupTable 生成，
 * 并由我们修改以添加 UINT64CONST。
 */
#define FLOAT_POW5_INV_BITCOUNT 59
static const uint64 FLOAT_POW5_INV_SPLIT[31] = {
	UINT64CONST(576460752303423489), UINT64CONST(461168601842738791), UINT64CONST(368934881474191033), UINT64CONST(295147905179352826),
	UINT64CONST(472236648286964522), UINT64CONST(377789318629571618), UINT64CONST(302231454903657294), UINT64CONST(483570327845851670),
	UINT64CONST(386856262276681336), UINT64CONST(309485009821345069), UINT64CONST(495176015714152110), UINT64CONST(396140812571321688),
	UINT64CONST(316912650057057351), UINT64CONST(507060240091291761), UINT64CONST(405648192073033409), UINT64CONST(324518553658426727),
	UINT64CONST(519229685853482763), UINT64CONST(415383748682786211), UINT64CONST(332306998946228969), UINT64CONST(531691198313966350),
	UINT64CONST(425352958651173080), UINT64CONST(340282366920938464), UINT64CONST(544451787073501542), UINT64CONST(435561429658801234),
	UINT64CONST(348449143727040987), UINT64CONST(557518629963265579), UINT64CONST(446014903970612463), UINT64CONST(356811923176489971),
	UINT64CONST(570899077082383953), UINT64CONST(456719261665907162), UINT64CONST(365375409332725730)
};
#define FLOAT_POW5_BITCOUNT 61
static const uint64 FLOAT_POW5_SPLIT[47] = {
	UINT64CONST(1152921504606846976), UINT64CONST(1441151880758558720), UINT64CONST(1801439850948198400), UINT64CONST(2251799813685248000),
	UINT64CONST(1407374883553280000), UINT64CONST(1759218604441600000), UINT64CONST(2199023255552000000), UINT64CONST(1374389534720000000),
	UINT64CONST(1717986918400000000), UINT64CONST(2147483648000000000), UINT64CONST(1342177280000000000), UINT64CONST(1677721600000000000),
	UINT64CONST(2097152000000000000), UINT64CONST(1310720000000000000), UINT64CONST(1638400000000000000), UINT64CONST(2048000000000000000),
	UINT64CONST(1280000000000000000), UINT64CONST(1600000000000000000), UINT64CONST(2000000000000000000), UINT64CONST(1250000000000000000),
	UINT64CONST(1562500000000000000), UINT64CONST(1953125000000000000), UINT64CONST(1220703125000000000), UINT64CONST(1525878906250000000),
	UINT64CONST(1907348632812500000), UINT64CONST(1192092895507812500), UINT64CONST(1490116119384765625), UINT64CONST(1862645149230957031),
	UINT64CONST(1164153218269348144), UINT64CONST(1455191522836685180), UINT64CONST(1818989403545856475), UINT64CONST(2273736754432320594),
	UINT64CONST(1421085471520200371), UINT64CONST(1776356839400250464), UINT64CONST(2220446049250313080), UINT64CONST(1387778780781445675),
	UINT64CONST(1734723475976807094), UINT64CONST(2168404344971008868), UINT64CONST(1355252715606880542), UINT64CONST(1694065894508600678),
	UINT64CONST(2117582368135750847), UINT64CONST(1323488980084844279), UINT64CONST(1654361225106055349), UINT64CONST(2067951531382569187),
	UINT64CONST(1292469707114105741), UINT64CONST(1615587133892632177), UINT64CONST(2019483917365790221)
};

static inline uint32 fc_pow5Factor(uint32 fc_value)
{
	uint32		fc_count = 0;

	for (;;)
	{
		Assert(fc_value != 0);
		const uint32 fc_q = fc_value / 5;
		const uint32 fc_r = fc_value % 5;

		if (fc_r != 0)
			break;

		fc_value = fc_q;
		++fc_count;
	}
	return fc_count;
}

/* 返回 true 如果值能被 5^p 整除。 */
static inline bool fc_multipleOfPowerOf5(const uint32 fc_value, const uint32 fc_p)
{
	return fc_pow5Factor(fc_value) >= fc_p;
}

/* 返回 true 如果值能被 2^p 整除。 */
static inline bool fc_multipleOfPowerOf2(const uint32 fc_value, const uint32 fc_p)
{
	/* 返回 __builtin_ctz(value) >= p; */
	return (fc_value & ((1u << fc_p) - 1)) == 0;
}

/*
 * 避免使用 uint128_t 似乎会稍微快一点，尽管
 * uint128_t 生成的代码看起来稍微好看一些。
 */
static inline uint32 fc_mulShift(const uint32 fc_m, const uint64 fc_factor, const int32 fc_shift)
{
	/*
	 * 这里的强制类型转换可以帮助 MSVC 避免调用 __allmul 库
	 * 函数。
	 */
	const uint32 fc_factorLo = (uint32) (fc_factor);
	const uint32 fc_factorHi = (uint32) (fc_factor >> 32);
	const uint64 fc_bits0 = (uint64) fc_m * fc_factorLo;
	const uint64 fc_bits1 = (uint64) fc_m * fc_factorHi;

	Assert(fc_shift > 32);

#ifdef RYU_32_BIT_PLATFORM

	/*
	 * 在 32 位平台上，我们可以避免 64 位右移，因为我们只
	 * 需要结果的高 32 位，而移位值 > 32。
	 */
	const uint32 fc_bits0Hi = (uint32) (fc_bits0 >> 32);
	uint32		fc_bits1Lo = (uint32) (fc_bits1);
	uint32		fc_bits1Hi = (uint32) (fc_bits1 >> 32);

	fc_bits1Lo += fc_bits0Hi;
	fc_bits1Hi += (fc_bits1Lo < fc_bits0Hi);

	const int32 fc_s = fc_shift - 32;

	return (fc_bits1Hi << (32 - fc_s)) | (fc_bits1Lo >> fc_s);

#else							/* RYU_32_BIT_PLATFORM */

	const uint64 fc_sum = (fc_bits0 >> 32) + fc_bits1;
	const uint64 fc_shiftedSum = fc_sum >> (fc_shift - 32);

	Assert(fc_shiftedSum <= PG_UINT32_MAX);
	return (uint32) fc_shiftedSum;

#endif							/* RYU_32_BIT_PLATFORM */
}

static inline uint32 fc_mulPow5InvDivPow2(const uint32 fc_m, const uint32 fc_q, const int32 fc_j)
{
	return fc_mulShift(fc_m, FLOAT_POW5_INV_SPLIT[fc_q], fc_j);
}

static inline uint32 fc_mulPow5divPow2(const uint32 fc_m, const uint32 fc_i, const int32 fc_j)
{
	return fc_mulShift(fc_m, FLOAT_POW5_SPLIT[fc_i], fc_j);
}

static inline uint32 fc_decimalLength(const uint32 fc_v)
{
	/* 函数前提条件：v 不是一个 10 位数字。 */
	/* （9 位足以实现往返转换。） */
	Assert(fc_v < 1000000000);
	if (fc_v >= 100000000)
	{
		return 9;
	}
	if (fc_v >= 10000000)
	{
		return 8;
	}
	if (fc_v >= 1000000)
	{
		return 7;
	}
	if (fc_v >= 100000)
	{
		return 6;
	}
	if (fc_v >= 10000)
	{
		return 5;
	}
	if (fc_v >= 1000)
	{
		return 4;
	}
	if (fc_v >= 100)
	{
		return 3;
	}
	if (fc_v >= 10)
	{
		return 2;
	}
	return 1;
}

/* 一个浮动的小数，表示 m * 10^e。 */
typedef struct floating_decimal_32
{
	uint32		mantissa;
	int32		exponent;
} floating_decimal_32;

static inline floating_decimal_32
fc_f2d(const uint32 fc_ieeeMantissa, const uint32 fc_ieeeExponent)
{
	int32		fc_e2;
	uint32		fc_m2;

	if (fc_ieeeExponent == 0)
	{
		/* 我们减去 2，以便边界计算有 2 位额外的位。 */
		fc_e2 = 1 - FLOAT_BIAS - FLOAT_MANTISSA_BITS - 2;
		fc_m2 = fc_ieeeMantissa;
	}
	else
	{
		fc_e2 = fc_ieeeExponent - FLOAT_BIAS - FLOAT_MANTISSA_BITS - 2;
		fc_m2 = (1u << FLOAT_MANTISSA_BITS) | fc_ieeeMantissa;
	}

#if STRICTLY_SHORTEST
	const bool	even = (m2 & 1) == 0;
	const bool	acceptBounds = even;
#else
	const bool	fc_acceptBounds = false;
#endif

	/* 第 2 步：确定合法小数表示的区间。 */
	const uint32 fc_mv = 4 * fc_m2;
	const uint32 fc_mp = 4 * fc_m2 + 2;

	/* 隐式 bool -> int 转换。真为 1，假为 0。 */
	const uint32 fc_mmShift = fc_ieeeMantissa != 0 || fc_ieeeExponent <= 1;
	const uint32 fc_mm = 4 * fc_m2 - 1 - fc_mmShift;

	/* 第 3 步：使用 64 位算术转换为十进制幂基数。 */
	uint32		fc_vr,
				fc_vp,
				fc_vm;
	int32		fc_e10;
	bool		fc_vmIsTrailingZeros = false;
	bool		fc_vrIsTrailingZeros = false;
	uint8		fc_lastRemovedDigit = 0;

	if (fc_e2 >= 0)
	{
		const uint32 fc_q = log10Pow2(fc_e2);

		fc_e10 = fc_q;

		const int32 fc_k = FLOAT_POW5_INV_BITCOUNT + pow5bits(fc_q) - 1;
		const int32 fc_i = -fc_e2 + fc_q + fc_k;

		fc_vr = fc_mulPow5InvDivPow2(fc_mv, fc_q, fc_i);
		fc_vp = fc_mulPow5InvDivPow2(fc_mp, fc_q, fc_i);
		fc_vm = fc_mulPow5InvDivPow2(fc_mm, fc_q, fc_i);

		if (fc_q != 0 && (fc_vp - 1) / 10 <= fc_vm / 10)
		{
			/*
			 * 即使我们不打算在下面循环，我们也需要知道一个移除的数字。
			 * 我们可以在上面使用 q = X - 1，只是这会
			 * 需要 33 位用于结果，而我们发现即使在 64 位机器上 32 位
			 * 算术也更快。
			 */
			const int32 fc_l = FLOAT_POW5_INV_BITCOUNT + pow5bits(fc_q - 1) - 1;

			fc_lastRemovedDigit = (uint8) (fc_mulPow5InvDivPow2(fc_mv, fc_q - 1, -fc_e2 + fc_q - 1 + fc_l) % 10);
		}
		if (fc_q <= 9)
		{
			/*
			 * 适合 24 位的最大 5 的幂是 5^10，但是 q <= 9
			 * 似乎也是安全的。
			 *
			 * mp、mv 和 mm 中只能有一个可以是 5 的倍数（如果有的话）。
			 */
			if (fc_mv % 5 == 0)
			{
				fc_vrIsTrailingZeros = fc_multipleOfPowerOf5(fc_mv, fc_q);
			}
			else if (fc_acceptBounds)
			{
				fc_vmIsTrailingZeros = fc_multipleOfPowerOf5(fc_mm, fc_q);
			}
			else
			{
				fc_vp -= fc_multipleOfPowerOf5(fc_mp, fc_q);
			}
		}
	}
	else
	{
		const uint32 fc_q = log10Pow5(-fc_e2);

		fc_e10 = fc_q + fc_e2;

		const int32 fc_i = -fc_e2 - fc_q;
		const int32 fc_k = pow5bits(fc_i) - FLOAT_POW5_BITCOUNT;
		int32		fc_j = fc_q - fc_k;

		fc_vr = fc_mulPow5divPow2(fc_mv, fc_i, fc_j);
		fc_vp = fc_mulPow5divPow2(fc_mp, fc_i, fc_j);
		fc_vm = fc_mulPow5divPow2(fc_mm, fc_i, fc_j);

		if (fc_q != 0 && (fc_vp - 1) / 10 <= fc_vm / 10)
		{
			fc_j = fc_q - 1 - (pow5bits(fc_i + 1) - FLOAT_POW5_BITCOUNT);
			fc_lastRemovedDigit = (uint8) (fc_mulPow5divPow2(fc_mv, fc_i + 1, fc_j) % 10);
		}
		if (fc_q <= 1)
		{
			/*
			 * {vr,vp,vm} 是尾随零，如果 {mv,mp,mm} 至少有 q
			 * 个尾随 0 位。
			 */
			/* mv = 4 * m2，因此它总是至少有两个尾随 0 位。 */
			fc_vrIsTrailingZeros = true;
			if (fc_acceptBounds)
			{
				/*
				 * mm = mv - 1 - mmShift，因此当且仅当
				 * mmShift == 1 时它有 1 个尾随 0 位。
				 */
				fc_vmIsTrailingZeros = fc_mmShift == 1;
			}
			else
			{
				/*
				 * mp = mv + 2，因此它总是至少有 1 个尾随 0 位。
				 */
				--fc_vp;
			}
		}
		else if (fc_q < 31)
		{
			/* TODO(ulfjack): 在这里使用更紧的边界。 */
			fc_vrIsTrailingZeros = fc_multipleOfPowerOf2(fc_mv, fc_q - 1);
		}
	}

	/*
	 * 第 4 步：在合法表示的区间中找到最短的小数表示。
	 */
	uint32		fc_removed = 0;
	uint32		fc_output;

	if (fc_vmIsTrailingZeros || fc_vrIsTrailingZeros)
	{
		/* 一般情况，发生的频率很低（约 4.0%）。 */
		while (fc_vp / 10 > fc_vm / 10)
		{
			fc_vmIsTrailingZeros &= fc_vm - (fc_vm / 10) * 10 == 0;
			fc_vrIsTrailingZeros &= fc_lastRemovedDigit == 0;
			fc_lastRemovedDigit = (uint8) (fc_vr % 10);
			fc_vr /= 10;
			fc_vp /= 10;
			fc_vm /= 10;
			++fc_removed;
		}
		if (fc_vmIsTrailingZeros)
		{
			while (fc_vm % 10 == 0)
			{
				fc_vrIsTrailingZeros &= fc_lastRemovedDigit == 0;
				fc_lastRemovedDigit = (uint8) (fc_vr % 10);
				fc_vr /= 10;
				fc_vp /= 10;
				fc_vm /= 10;
				++fc_removed;
			}
		}

		if (fc_vrIsTrailingZeros && fc_lastRemovedDigit == 5 && fc_vr % 2 == 0)
		{
			/* 即使确切数字是 .....50..0 也要进行四舍五入。 */
			fc_lastRemovedDigit = 4;
		}

		/*
		 * 如果 vr 超出边界或我们需要向上四舍五入，则我们需要
		 * 取 vr + 1。
		 */
		fc_output = fc_vr + ((fc_vr == fc_vm && (!fc_acceptBounds || !fc_vmIsTrailingZeros)) || fc_lastRemovedDigit >= 5);
	}
	else
	{
		/*
		 * 专门针对常见情况（约 96.0%）。下面的百分比相对于此。
		 *
		 * 下面的循环迭代（大约）：0: 13.6%，1: 70.7%，2:
		 * 14.1%，3: 1.39%，4: 0.14%，5+: 0.01%
		 */
		while (fc_vp / 10 > fc_vm / 10)
		{
			fc_lastRemovedDigit = (uint8) (fc_vr % 10);
			fc_vr /= 10;
			fc_vp /= 10;
			fc_vm /= 10;
			++fc_removed;
		}

		/*
		 * 如果 vr 超出边界或我们需要向上四舍五入，则我们需要
		 * 取 vr + 1。
		 */
		fc_output = fc_vr + (fc_vr == fc_vm || fc_lastRemovedDigit >= 5);
	}

	const int32 fc_exp = fc_e10 + fc_removed;

	floating_decimal_32 fc_fd;

	fc_fd.exponent = fc_exp;
	fc_fd.mantissa = fc_output;
	return fc_fd;
}

static inline int fc_to_chars_f(const floating_decimal_32 fc_v, const uint32 fc_olength, char *const fc_result)
{
	/* 步骤 5：打印十进制表示。 */
	int			fc_index = 0;

	uint32		fc_output = fc_v.mantissa;
	int32		fc_exp = fc_v.exponent;

	/*----
	 * 在进入时，mantissa * 10^exp 是需要输出的结果。
	 * 调用者如果需要已经处理了负号。
	 *
	 * 我们想根据输出长度和指数在某处插入小数点，这可能意味着添加零：
	 *
	 *            exp  | 格式
	 *            1+   |  ddddddddd000000
	 *            0    |  ddddddddd
	 *  -1 .. -len+1   |  dddddddd.d 到 d.ddddddddd
	 *  -len ...       |  0.ddddddddd 到 0.000dddddd
	 */
	uint32		fc_i = 0;
	int32		fc_nexp = fc_exp + fc_olength;

	if (fc_nexp <= 0)
	{
		/* -nexp 是在 '.' 后添加的 0 的数量 */
		Assert(fc_nexp >= -3);
		/* 0.000ddddd */
		fc_index = 2 - fc_nexp;
		/* 复制 8 字节而不是 5 以让编译器优化 */
		memcpy(fc_result, "0.000000", 8);
	}
	else if (fc_exp < 0)
	{
		/*
		 * dddd.dddd；在开头留空位，移动小数点到后面
		 */
		fc_index = 1;
	}
	else
	{
		/*
		 * 我们可以通过预先填充零来节省一些后面的代码。我们知道
		 * 在这种形式中最多只能有 6 位输出数字，否则
		 * 我们不会选择定点输出。memset 8 而不是 6
		 * 字节以让编译器优化它。
		 */
		Assert(fc_exp < 6 && fc_exp + fc_olength <= 6);
		memset(fc_result, '0', 8);
	}

	while (fc_output >= 10000)
	{
		const uint32 fc_c = fc_output - 10000 * (fc_output / 10000);
		const uint32 fc_c0 = (fc_c % 100) << 1;
		const uint32 fc_c1 = (fc_c / 100) << 1;

		fc_output /= 10000;

		memcpy(fc_result + fc_index + fc_olength - fc_i - 2, DIGIT_TABLE + fc_c0, 2);
		memcpy(fc_result + fc_index + fc_olength - fc_i - 4, DIGIT_TABLE + fc_c1, 2);
		fc_i += 4;
	}
	if (fc_output >= 100)
	{
		const uint32 fc_c = (fc_output % 100) << 1;

		fc_output /= 100;
		memcpy(fc_result + fc_index + fc_olength - fc_i - 2, DIGIT_TABLE + fc_c, 2);
		fc_i += 2;
	}
	if (fc_output >= 10)
	{
		const uint32 fc_c = fc_output << 1;

		memcpy(fc_result + fc_index + fc_olength - fc_i - 2, DIGIT_TABLE + fc_c, 2);
	}
	else
	{
		fc_result[fc_index] = (char) ('0' + fc_output);
	}

	if (fc_index == 1)
	{
		/*
		 * nexp 在这里是 1..6，表示小数点前面的数字
		 * 的数量。值为 7+ 不可能，因为当显示指数达到 6 时，我们切换到
		 * 科学记数法。
		 */
		Assert(fc_nexp < 7);
		/* gcc 似乎只想为小的 2^n 优化 memmove */
		if (fc_nexp & 4)
		{
			memmove(fc_result + fc_index - 1, fc_result + fc_index, 4);
			fc_index += 4;
		}
		if (fc_nexp & 2)
		{
			memmove(fc_result + fc_index - 1, fc_result + fc_index, 2);
			fc_index += 2;
		}
		if (fc_nexp & 1)
		{
			fc_result[fc_index - 1] = fc_result[fc_index];
		}
		fc_result[fc_nexp] = '.';
		fc_index = fc_olength + 1;
	}
	else if (fc_exp >= 0)
	{
		/* 我们之前提供了尾随零，现在只需设置长度。 */
		fc_index = fc_olength + fc_exp;
	}
	else
	{
		fc_index = fc_olength + (2 - fc_nexp);
	}

	return fc_index;
}

static inline int fc_to_chars(const floating_decimal_32 fc_v, const bool fc_sign, char *const fc_result)
{
	/* 步骤 5：打印十进制表示。 */
	int			fc_index = 0;

	uint32		fc_output = fc_v.mantissa;
	uint32		fc_olength = fc_decimalLength(fc_output);
	int32		fc_exp = fc_v.exponent + fc_olength - 1;

	if (fc_sign)
		fc_result[fc_index++] = '-';

	/*
	 * 定点输出的阈值选择与 printf
	 * 默认值匹配。请注意，to_chars_f 的代码和
	 * FLOAT_SHORTEST_DECIMAL_LEN 的值对这些阈值敏感。
	 */
	if (fc_exp >= -4 && fc_exp < 6)
		return fc_to_chars_f(fc_v, fc_olength, fc_result + fc_index) + fc_sign;

	/*
	 * 如果 v.exponent 恰好为 0，我们可能是通过小整数快速路径到达这里，在这种情况下 v.mantissa 可能包含尾随（十进制）零。对于科学记数法，我们需要将这些零移动到指数中。（对于定点数，这无关紧要，这就是为什么我们在这里而不是上面处理它。）
	 *
	 * 由于我们已经根据旧的十进制长度计算了显示指数（exp），该值在这里不会改变。相反，我们只需减少每移除一个数字的显示长度。
	 *
	 * 如果我们不是通过快速路径到达这里，原始指数通常不会是 0，并且不会有尾随零，因此我们最多只需额外的一个 div10/multiply 成本。通过在除以 10 之前检查是否可以被 2 整除，我们可以回收一半的成本。
	 */
	if (fc_v.exponent == 0)
	{
		while ((fc_output & 1) == 0)
		{
			const uint32 fc_q = fc_output / 10;
			const uint32 fc_r = fc_output - 10 * fc_q;

			if (fc_r != 0)
				break;
			fc_output = fc_q;
			--fc_olength;
		}
	}

	/*----
	 * 打印十进制数字。
	 * 以下代码相当于：
	 *
	 * for (uint32 i = 0; i < olength - 1; ++i) {
	 *   const uint32 c = output % 10; output /= 10;
	 *   result[index + olength - i] = (char) ('0' + c);
	 * }
	 * result[index] = '0' + output % 10;
	 */
	uint32		fc_i = 0;

	while (fc_output >= 10000)
	{
		const uint32 fc_c = fc_output - 10000 * (fc_output / 10000);
		const uint32 fc_c0 = (fc_c % 100) << 1;
		const uint32 fc_c1 = (fc_c / 100) << 1;

		fc_output /= 10000;

		memcpy(fc_result + fc_index + fc_olength - fc_i - 1, DIGIT_TABLE + fc_c0, 2);
		memcpy(fc_result + fc_index + fc_olength - fc_i - 3, DIGIT_TABLE + fc_c1, 2);
		fc_i += 4;
	}
	if (fc_output >= 100)
	{
		const uint32 fc_c = (fc_output % 100) << 1;

		fc_output /= 100;
		memcpy(fc_result + fc_index + fc_olength - fc_i - 1, DIGIT_TABLE + fc_c, 2);
		fc_i += 2;
	}
	if (fc_output >= 10)
	{
		const uint32 fc_c = fc_output << 1;

		/*
		 * 我们不能在这里使用 memcpy：小数点位于这两个数字之间。
		 */
		fc_result[fc_index + fc_olength - fc_i] = DIGIT_TABLE[fc_c + 1];
		fc_result[fc_index] = DIGIT_TABLE[fc_c];
	}
	else
	{
		fc_result[fc_index] = (char) ('0' + fc_output);
	}

	/* 如有必要，打印小数点。 */
	if (fc_olength > 1)
	{
		fc_result[fc_index + 1] = '.';
		fc_index += fc_olength + 1;
	}
	else
	{
		++fc_index;
	}

	/* 打印指数。 */
	fc_result[fc_index++] = 'e';
	if (fc_exp < 0)
	{
		fc_result[fc_index++] = '-';
		fc_exp = -fc_exp;
	}
	else
		fc_result[fc_index++] = '+';

	memcpy(fc_result + fc_index, DIGIT_TABLE + 2 * fc_exp, 2);
	fc_index += 2;

	return fc_index;
}

static inline bool fc_f2d_small_int(const uint32 fc_ieeeMantissa,
			  const uint32 fc_ieeeExponent,
			  floating_decimal_32 *fc_v)
{
	const int32 fc_e2 = (int32) fc_ieeeExponent - FLOAT_BIAS - FLOAT_MANTISSA_BITS;

	/*
	 * 避免在这里使用多个“return false;”，因为这会导致编译器
	 * 内联多个f2d的副本，这是不理想的。
	 */

	if (fc_e2 >= -FLOAT_MANTISSA_BITS && fc_e2 <= 0)
	{
		/*----
		 * 由于 2^23 <= m2 < 2^24 且 0 <= -e2 <= 23：
		 *   1 <= f = m2 / 2^-e2 < 2^24。
		 *
		 * 测试有效数的低 -e2 位是否为 0，即测试小数部分是否为 0。
		 * 我们可以在这里使用 ieeeMantissa，因为该隐含的 1 位
		 * 绝不会被测试；只有在 e2 < -FLOAT_MANTISSA_BITS 时
		 * 隐含的 1 才能是小数部分的一部分，而我们已经检查过了。
		 * （例如 0.5 使得 ieeeMantissa == 0 且 e2 == -24）
		 */
		const uint32 fc_mask = (1U << -fc_e2) - 1;
		const uint32 fc_fraction = fc_ieeeMantissa & fc_mask;

		if (fc_fraction == 0)
		{
			/*----
			 * f 是范围 [1, 2^24) 内的整数。
			 * 注意：尾数可能包含尾随（小数）0。
			 * 注意：由于 2^24 < 10^9，因而无需调整
			 * decimalLength()。
			 */
			const uint32 fc_m2 = (1U << FLOAT_MANTISSA_BITS) | fc_ieeeMantissa;

			fc_v->mantissa = fc_m2 >> -fc_e2;
			fc_v->exponent = 0;
			return true;
		}
	}

	return false;
}

/*
 * 将给定浮点数的最短小数表示存储为一个
 * 未终止的字符串在调用者提供的缓冲区中（该缓冲区必须至少
 * 存放 FLOAT_SHORTEST_DECIMAL_LEN-1 字节）。
 *
 * 返回存储的字节数。
 */
int float_to_shortest_decimal_bufn(float fc_f, char *fc_result)
{
	/*
	 * 第一步：解码浮点数，并统一规范化和非规范化情况。
	 */
	const uint32 fc_bits = float_to_bits(fc_f);

	/* 将位解码为符号、尾数和指数。 */
	const bool	fc_ieeeSign = ((fc_bits >> (FLOAT_MANTISSA_BITS + FLOAT_EXPONENT_BITS)) & 1) != 0;
	const uint32 fc_ieeeMantissa = fc_bits & ((1u << FLOAT_MANTISSA_BITS) - 1);
	const uint32 fc_ieeeExponent = (fc_bits >> FLOAT_MANTISSA_BITS) & ((1u << FLOAT_EXPONENT_BITS) - 1);

	/* 情况区分；对于简单情况提前退出。 */
	if (fc_ieeeExponent == ((1u << FLOAT_EXPONENT_BITS) - 1u) || (fc_ieeeExponent == 0 && fc_ieeeMantissa == 0))
	{
		return copy_special_str(fc_result, fc_ieeeSign, (fc_ieeeExponent != 0), (fc_ieeeMantissa != 0));
	}

	floating_decimal_32 fc_v;
	const bool	fc_isSmallInt = fc_f2d_small_int(fc_ieeeMantissa, fc_ieeeExponent, &fc_v);

	if (!fc_isSmallInt)
	{
		fc_v = fc_f2d(fc_ieeeMantissa, fc_ieeeExponent);
	}

	return fc_to_chars(fc_v, fc_ieeeSign, fc_result);
}

/*
 * 将给定浮点数的最短小数表示存储为一个
 * null 终止字符串在调用者提供的缓冲区中（该缓冲区必须至少
 * 存放 FLOAT_SHORTEST_DECIMAL_LEN 字节）。
 *
 * 返回字符串长度。
 */
int float_to_shortest_decimal_buf(float fc_f, char *fc_result)
{
	const int	fc_index = float_to_shortest_decimal_bufn(fc_f, fc_result);

	/* 终止字符串。 */
	Assert(fc_index < FLOAT_SHORTEST_DECIMAL_LEN);
	fc_result[fc_index] = '\0';
	return fc_index;
}

/*
 * 返回最短的十进制表示作为一个以空字符结束的 palloc'd
 * 字符串（在后端之外，使用 malloc()）。
 *
 * 调用者负责释放结果。
 */
char * float_to_shortest_decimal(float fc_f)
{
	char	   *const fc_result = (char *) palloc(FLOAT_SHORTEST_DECIMAL_LEN);

	float_to_shortest_decimal_buf(fc_f, fc_result);
	return fc_result;
}
